import os
import re
import nltk
import numpy as np
import pickle

from wrapper import NerWrapper
from entityobject import EntityObject
from phrase_chunker import chunkPhrase, extractNounPhrase
from pleonastic import isPleonastic

global dir 
dir = os.getcwd()

femalePronouns = ["her", "hers", "herself", "she", "Her", "She"]
malePronouns = ["he", "him", "himself", "his", "He", "Him", "His"]
global objectPronouns
# objectPronouns = ["it", "its", "itself", "they", "their", "theirs", "them", "themselves", "It", "Its", "They", "Their"]
objectPronouns = ["it", "its", "itself", "It", "Its"]
global personPronouns
personPronouns = femalePronouns + malePronouns
allPronouns = personPronouns + objectPronouns

# Fungsi untuk melakukan POS tag pada kalimat
# sentence : kalimat yang akan di-tag
# return : kalimat yang telah dilabeli pos tag
def tagSentence(sentence):
	words = nltk.word_tokenize(str(sentence))
	tags = nltk.pos_tag(words)
	
	return tags

# Fungsi untuk melakukan NER pada kalimat
# sentence : kalimat yang akan di-tag
# return : list NE 
def extractNE(sentence):
	NERList = []
	temp = NerWrapper.get_ner(sentence)
	
	NERList.append([person.person_name for person in temp[0]])
	NERList.append(temp[1])
	NERList.append(temp[2])
	
	return NERList

# Fungsi untuk mengekstrak semua NP dari sebuah kalimat
# pos : urutan kalimat
# taggedSentence : kalimat yang telah dilabeli pos tag
# return : list NP
def extractNP(pos, taggedSentence):
	entityList = []
	
	phrase = extractNounPhrase(chunkPhrase(taggedSentence))
	
	for NP in phrase:
		if isGenitive(NP):
			NP = NP[:NP.find("'s")-1]
		entity = EntityObject();
		entity.str = NP
		entity.pos = pos
		entity.id = -1
		entityList.append(entity)
		
	return entityList

# Fungsi untuk mengekstrak semua NE Person & Organization dari sebuah kalimat
# pos : urutan kalimat
# NEList : list NE di kalimat
# return : list Person & Organization
def extractPersonOrganization(pos, NEList):
	entityList = []
	
	list_PER = NEList[0]
	list_ORG = NEList[1]
	
	for PER in list_PER:
		entity = EntityObject();
		entity.str = PER
		entity.pos = pos
		entity.id = -1
		entityList.append(entity)
	
	for ORG in list_ORG:
		entity = EntityObject();
		entity.str = ORG
		entity.pos = pos
		entity.id = -1
		entityList.append(entity)
	
	return entityList

def redundancyCheck(OP, OPWords):
	found = -1
	i = 0
	while i < len(OPWords) and found < 0:
		j = 0
		while j < len(OPWords[i]) and found <0:
			if OP[0] == OPWords[i][j]:
				found = i
			j += 1
		i += 1
	return found

def cleanPersonOrganization(OPList):
	delete = {}
	OPWords = []
	for OP in OPList:
		OPWord = nltk.word_tokenize(OP.str)
		OPWords.append(OPWord)
	o = 0
	while o < len(OPWords):
		red = redundancyCheck(OPWords[o], OPWords)
		if len(OPWords[o]) == 1 and red >= 0:
			delete[o] = red
		o += 1
	
	for key, value in delete.items():
		OPList[key].str = OPList[value].str
	return OPList

# Fungsi untuk memisahkan teks menjadi kalimat-kalimat penyusunnya
# text : teks
# return : list kalimat
def splitSentence(text):
	sentenceList = []
	
	tokenizer = nltk.data.load('tokenizers/punkt/english.pickle')
	sentenceList = tokenizer.tokenize(text, True)
	
	return sentenceList

# Fungsi untuk menghapus article (a, an, the) dari sebuah string
# str : string
# return : string yang telah dihapus article-nya
def removeArticle(str):
	str = re.sub(r'\s*[aA]\s+', ' ', str)
	str = re.sub(r'\s*[aA]n\s+', ' ', str)
	str = re.sub(r'\s*[tT]he\s+', ' ', str)
	
	return str.strip()

# Fungsi untuk menghapus demonstrative pronoun (this, that, these, those) dari sebuah string
# str : string
# return : string yang telah dihapus demonstrative pronoun-nya
def removeDeterminer(str):
	str = re.sub(r'\s*[tT]his\s+', ' ', str)
	str = re.sub(r'\s*[tT]hat\s+', ' ', str)
	str = re.sub(r'\s*[tT]hese\s+', ' ', str)
	str = re.sub(r'\s*[tT]hose\s+', ' ', str)
	
	return str.strip()

# Fungsi untuk menentukan apakah e1 dan e2 merupakan string yang sama atau tidak. Pencocokan dilakukan setelah menghapus article (a, an, the) dan demonstrative pronoun (this, that, these, those).
# entity1 : entity 1 (obyek yang diacu)
# entity2 : entity 2 (obyek yang mengacu)
# return : 1 / 0
def isStringMatch(entity1, entity2):
	str1 = removeArticle(entity1.str)
	str1 = removeDeterminer(str1)
	
	str2 = removeArticle(entity2.str)
	str2 = removeDeterminer(str2)
	
	if(str1.lower() == str2.lower()):
		return 1
	else:
		return 0

# Fungsi untuk menentukan apakah e1 dan e2 merupakan string yang sama secara parsial atau tidak. Pencocokan dilakukan setelah menghapus article (a, an, the) dan demonstrative pronoun (this, that, these, those).
# entity1 : entity 1 (obyek yang diacu)
# entity2 : entity 2 (obyek yang mengacu)
# return : 1 / 0
def isStringMatchPartial(entity1, entity2):
	str1 = removeArticle(entity1.str)
	str1 = removeDeterminer(str1)
	
	str2 = removeArticle(entity2.str)
	str2 = removeDeterminer(str2)
	
	words1 = str1.lower().split(" ")
	words2 = str2.lower().split(" ")
	
	#String2 merupakan subset dari String1, belum tentu terurut
	found = False
	i = 0
	while((i < len(words2)) and (not(found))):
		temp = words2[i]
		if(temp in words1):
			found = True
		
		i += 1
	
	if(found):
		return 1
	
	#String1 merupakan subset dari String2, belum tentu terurut
	found = False
	i = 0
	while((i < len(words1)) and (not(found))):
		temp = words1[i]
		if(temp in words2):
			found = True
		
		i += 1
	
	if(found):
		return 1
	
	return 0

# Fungsi untuk menentukan apakah e1 dan e2 sama-sama tidak mengandung tanda baca atau tidak.
# entity1 : entity 1 (obyek yang diacu)
# entity2 : entity 2 (obyek yang mengacu)
# return : 1 / 0
def isMatchNoPunctuation(entity1, entity2):
	match1 = re.match(r'^[a-zA-Z0-1\s]+$', entity1.str)
	match2 = re.match(r'^[a-zA-Z0-1\s]+$', entity2.str)
	
	if(match1 and match2):
		return 1
	else:
		return 0

# Fungsi untuk menentukan apakah salah satu entitas merupakan kepanjangan dari entitas lainnya atau tidak. Pengecekan dilakukan dengan membandingkan huruf besar yang digunakan pada kedua entitas.
# entity1 : entity 1 (obyek yang diacu)
# entity2 : entity 2 (obyek yang mengacu)
# return : 1 / 0
def isAbbreviation(entity1, entity2):
	str1 = removeArticle(entity1.str)
	str1 = removeDeterminer(str1)
	
	str2 = removeArticle(entity2.str)
	str2 = removeDeterminer(str2)
	
	isAbbreviationForm1 = re.match(r'^[A-Z]+[a-z]*[A-Z]+$', str1)
	isAbbreviationForm2 = re.match(r'^[A-Z]+[a-z]*[A-Z]+$', str2)
	
	#Cek apakah entity2 merupakan kepanjangan dari entity1
	if(isAbbreviationForm1):
		chars = list(str1)
		words = str2.split(" ")
		
		i = 0
		j = 0
		matchAll = True
		while((i < len(chars)) and (j < len(words)) and (matchAll)):
			if(chars[i].isupper() and words[j].istitle()):
				if(not(words[j][0] == chars[i])):
					matchAll = False
				
				i += 1
				j += 1
			elif(chars[i].islower() and words[j].islower()):
				if(not(words[j][0] == chars[i])):
					matchAll = False
				
				i += 1
				j += 1
			elif(chars[i].isupper() and words[j].islower()):
				j += 1
			elif(chars[i].islower() and words[j].isupper()):
				i += 1
			else:
				i += 1
				j += 1
		
		if((i == len(chars)) and (j <= len(words)) and (matchAll)):
			return 1
		else:
			return 0
	
	#Cek apakah entity1 merupakan kepanjangan dari entity2
	if(isAbbreviationForm2):
		chars = list(str2)
		words = str1.split(" ")
		
		i = 0
		j = 0
		matchAll = True
		while((i < len(chars)) and (j < len(words)) and (matchAll)):
			if(chars[i].isupper() and words[j].istitle()):
				if(not(words[j][0] == chars[i])):
					matchAll = False
				
				i += 1
				j += 1
			elif(chars[i].islower() and words[j].islower()):
				if(not(words[j][0] == chars[i])):
					matchAll = False
				
				i += 1
				j += 1
			elif(chars[i].isupper() and words[j].islower()):
				j += 1
			elif(chars[i].islower() and words[j].isupper()):
				i += 1
			else:
				i += 1
				j += 1
		
		if((i == len(chars)) and (j <= len(words)) and (matchAll)):
			return 1
		else:
			return 0
	
	return 0

# Fungsi untuk menentukan apakah sebuah entitas merupakan pronoun atau tidak.
# entity : entity (obyek)
# sentence_tagged : kalimat dimana obyek berada, yang telah dilabeli pos tag
# return : 1 / 0
def isPronoun(entity, sentence_tagged):
	word = entity.str.split(" ")
	
	if(len(word) > 1):
		return 0
	else:
		i = 0
		match = False
		
		while((i < len(sentence_tagged)) and (not match)):
			if(entity.str == sentence_tagged[i][0]):
				if((sentence_tagged[i][1] == "PRP") or (sentence_tagged[i][1] == "PRP$")):
					match = True
			
			i += 1
		
		if(match):
			return 1
		else:
			return 0

# Fungsi untuk menentukan apakah sebuah entitas merupakan possessive pronoun atau tidak.
# entity : entity (obyek)
# sentence_tagged : kalimat dimana obyek berada, yang telah dilabeli pos tag
# return : 1 / 0
def isPossessivePronoun(entity, sentence_tagged):
	word = entity.str.split(" ")
	
	i = 0
	j = 0
	match = False
	
	while((i < len(sentence_tagged)) and (j < len(word)) and (not match)):
		if(word[j] == sentence_tagged[i][0]):
			if(sentence_tagged[i][1] == "PRP$"):
				match = True
				entity.str = word[j]
			j += 1
		
		i += 1
	
	if(match):
		return 1
	else:
		return 0

def isGenitive(entity):
	if " 's" in entity:
		return 1
	else:
		return 0

# Fungsi untuk menentukan apakah e2 merupakan definite NP (dimulai dengan kata the) atau tidak.
# entity : entity (obyek)
# return : 1 / 0
def isDefiniteNP(entity):
	if(re.match(r'^[tT]he.+', entity.str)):
		return 1
	else:
		return 0

# Fungsi untuk menentukan apakah e2 merupakan demos=nstrative NP (dimulai dengan kata the) atau tidak.
# entity : entity (obyek)
# return : 1 / 0
def isDemonstrativeNP(entity):
	if((re.match(r'^[tT]his.+', entity.str)) or (re.match(r'^[tT]hat.+', entity.str)) or (re.match(r'^[tT]hese.+', entity.str)) or (re.match(r'^[tT]hose.+', entity.str))):
		return 1
	else:
		return 0

# Fungsi untuk menentukan apakah kedua entittas e1 dan e2 merupakan proper name atau tidak.
# entity1 : entity 1 (obyek yang diacu)
# entity2 : entity 2 (obyek yang mengacu)
# sentence_tagged1 : kalimat dimana obyek 1 berada, yang telah dilabeli pos tag
# sentence_tagged2 : kalimat dimana obyek 2 berada, yang telah dilabeli pos tag
# return : 1 / 0
def isProperName(entity1, entity2, sentence_tagged1, sentence_tagged2):
	str1 = removeArticle(entity1.str)
	str1 = removeDeterminer(str1)
	
	str2 = removeArticle(entity2.str)
	str2 = removeDeterminer(str2)
	
	word1 = str1.split(" ")
	word2 = str2.split(" ")
	
	i = 0
	match1 = False
	
	while((i < len(word1)) and (not match1)):
		j = 0
		while((j < len(sentence_tagged1)) and (not match1)):
			if(word1[i] == sentence_tagged1[j][0]):
				if((sentence_tagged1[j][1] == "NNP") or (sentence_tagged1[j][1] == "NNPS")):
					match1 = True
			j += 1
		
		i += 1
	
	i = 0
	match2 = False
	
	while((i < len(word2)) and (not match2)):
		j = 0
		while((j < len(sentence_tagged2)) and (not match2)):
			if(word2[i] == sentence_tagged2[j][0]):
				if((sentence_tagged2[j][1] == "NNP") or (sentence_tagged2[j][1] == "NNPS")):
					match2 = True
			j += 1
		
		i += 1
	
	if(match1 and match2):
		return 1
	else:
		return 0

# Fungsi untuk menentukan jarak kalimat antara kalimat dimana e1 berada dan kalimat dimana e2 berada.
# entity1 : entity 1 (obyek yang diacu)
# entity2 : entity 2 (obyek yang mengacu)
# return : int >= 0
def countSentenceDistance(entity1, entity2):
	distance = int(entity2.pos - entity1.pos)
	
	return distance

# Fungsi untuk menentukan tipe entitas dari masing-masing entitas e1 dan e2. Entitas yang didefinisikan mencakup Person, Organization, dan Location. 
# entity : entity (obyek)
# NER_list : list NE di kalimat dimana obyek berada
# return : 0 / 1 / 2 / 3
def extractEntityType(entity, NER_list):
	list_PER = NER_list[0]
	list_ORG = NER_list[1]
	list_LOC = NER_list[2]
	
	i = 0
	while(i < len(list_PER)):
		if((list_PER[i].find(entity.str) != -1) or (entity.str.find(list_PER[i]) != -1)):
			return 1
		i += 1
		
	i = 0
	while(i < len(list_ORG)):
		if((list_ORG[i].find(entity.str) != -1) or (entity.str.find(list_ORG[i]) != -1)):
			return 2
		i += 1
	
	i = 0
	while(i < len(list_LOC)):
		if((list_LOC[i].find(entity.str) != -1) or (entity.str.find(list_LOC[i]) != -1)):
			return 3
		i += 1
	
	return 0

# Fungsi untuk menentukan apakah e1 dan e2 sama dalam hal jumlah (tunggal atau jamak) atau tidak.
# entity1 : entity 1 (obyek yang diacu)
# entity2 : entity 2 (obyek yang mengacu)
# sentence_tagged1 : kalimat dimana obyek 1 berada, yang telah dilabeli pos tag
# sentence_tagged2 : kalimat dimana obyek 2 berada, yang telah dilabeli pos tag
# return : 1 / 0
def isNumberAgree(entity1, entity2, sentence_tagged1, sentence_tagged2):
	singularPronoun = ["i", "me", "my", "mine", "myself", "you", "your", "yours", "yourself", "he", "him", "his", "himself", "she", "her", "hers", "herself", "it", "its", "itself"]
	pluralPronoun = ["we", "us", "our", "ours", "ourselves", "they", "them", "their", "theirs", "themselves"]
	
	#Cek number dari entity1 (NE)
	word1 = entity1.str.split(" ")
	
	i = 0
	isPlural1 = False
	
	while((i < len(word1)) and (not isPlural1)):
		j = 0
		while((j < len(sentence_tagged1)) and (not isPlural1)):
			if(word1[i] == sentence_tagged1[j][0]):
				if((sentence_tagged1[j][1] == "NNPS") or (sentence_tagged1[j][1] == "NNS")):
					isPlural1 = True
			j += 1
		
		i += 1
	
	#Cek number dari entity2
	isPlural2 = False
	
	if(isPronoun(entity2, sentence_tagged2)):
		temp = entity2.str
		temp = temp.lower()
		
		if(temp in pluralPronoun):
			isPlural2 = True
		elif(temp in singularPronoun):
			isPlural2 = False
	else:
		word2 = entity2.str.split(" ")
		i = 0
		isPlural2 = False
		
		while((i < len(word2)) and (not isPlural2)):
			j = 0
			while((j < len(sentence_tagged2)) and (not isPlural2)):
				if(word2[i] == sentence_tagged2[j][0]):
					if((sentence_tagged2[j][1] == "NNPS") or (sentence_tagged2[j][1] == "NNS")):
						isPlural2 = True
				j += 1
			
			i += 1
	
	if(isPlural1 and isPlural2):
		return 1
	elif((not isPlural1) and (not isPlural2)):
		return 1
	else:
		return 0

def isEntityBefore(entity1, entity2, sentenceList):
	if entity1.pos < entity2.pos:
		return 1
	elif entity1. pos == entity2.pos:
		idx1 = sentenceList[entity1.pos].find(entity1.str)
		if entity2.str.islower():
			idx2 = sentenceList[entity2.pos].find(" "+entity2.str+" ")
		else:
			idx2 = sentenceList[entity2.pos].find(entity2.str+" ")
		if idx1 >= 0 and idx2 >= 0 and idx1 < idx2:
			return 1
		else:
			return 0
	else:
		return 0

# Fungsi untuk menentukan apakah ada entitas lain di antara e1 dan e2 di dalam teks.
# entity1 : entity 1 (obyek yang diacu)
# entity2 : entity 2 (obyek yang mengacu)
# sentenceList : list kalimat dari teks dimana entitas berada
# entityList : list NE dari teks dimana entitas berada
# return : 1 / 0
def isAnyEntityBefore(entity1, entity2, sentenceList, entityList):
	i = 0
	Found = False
	while((i < len(entityList)) and (not(Found))):
		if((entity1.pos < entityList[i].pos) and (entity1.str != entityList[i].str) and (entity2.pos > entityList[i].pos)):
			Found = True
		elif((entity1.pos == entityList[i].pos) and (entity1.str != entityList[i].str)):
			idx1 = sentenceList[entity1.pos].find(entity1.str)
			idx2 = sentenceList[entityList[i].pos].find(entityList[i].str)
			idx3 = sentenceList[entity2.pos].find(entity2.str)
			
			if(entity2.pos == entity1.pos):
				if((idx2 > idx1) and (idx3 > idx2)):
					Found = True
			else:
				if(idx2 > idx1):
					Found = True
		elif((entity2.pos == entityList[i].pos) and (entity1.str != entityList[i].str)):
			idx1 = sentenceList[entity1.pos].find(entity1.str)
			idx2 = sentenceList[entityList[i].pos].find(entityList[i].str)
			idx3 = sentenceList[entity2.pos].find(entity2.str)
			
			if(entity1.pos == entity2.pos):
				if((idx2 < idx3) and (idx1 < idx2)):
					Found = True
			else:
				if(idx2 < idx3):
					Found = True
		i += 1
	
	if(Found):
		return 1
	else:
		return 0

def isTypeAgree(entity0, entity2, NEList0, NEList2):
	if extractEntityType(entity0, NEList0) == extractEntityType(entity2, NEList2):
		return True
	elif extractEntityType(entity0, NEList0) == 1 and entity2.str in personPronouns:
		return True
	elif extractEntityType(entity0, NEList0) == 2 and entity2.str in objectPronouns:
		return True
	else:
		return False

# Fungsi untuk menentukan apakah ada entitas lain di antara e1 dan e2, yang bertipe sama dengan e2 di dalam teks.
# entity1 : entity 1 (obyek yang diacu)
# entity2 : entity 2 (obyek yang mengacu)
# sentenceList : list kalimat dari teks dimana entitas berada
# entityList : list NE dari teks dimana entitas berada
# return : 1 / 0
def isAnySimilarEntityBefore(entity1, entity2, sentenceList, entityList, NELists):
	i = 0
	Found = False
	while((i < len(entityList)) and (not(Found))):
		if((entity1.pos < entityList[i].pos) and (entity1.str != entityList[i].str) and (entity2.pos > entityList[i].pos)):
			if isTypeAgree(entityList[i], entity2, NELists[entityList[i].pos], NELists[entity2.pos]):
				Found = True
		elif((entity1.pos == entityList[i].pos) and (entity1.str != entityList[i].str)):
			idx1 = sentenceList[entity1.pos].find(entity1.str)
			idx2 = sentenceList[entityList[i].pos].find(entityList[i].str)
			idx3 = sentenceList[entity2.pos].find(entity2.str)
			
			if(entity2.pos == entity1.pos):
				if((idx2 > idx1) and (idx3 > idx2)):
					if isTypeAgree(entityList[i], entity2, NELists[entityList[i].pos], NELists[entity2.pos]):
						Found = True
			else:
				if(idx2 > idx1):
					if isTypeAgree(entityList[i], entity2, NELists[entityList[i].pos], NELists[entity2.pos]):
						Found = True
		elif((entity2.pos == entityList[i].pos) and (entity1.str != entityList[i].str)):
			idx1 = sentenceList[entity1.pos].find(entity1.str)
			idx2 = sentenceList[entityList[i].pos].find(entityList[i].str)
			idx3 = sentenceList[entity2.pos].find(entity2.str)
			
			if(entity1.pos == entity2.pos):
				if((idx2 < idx3) and (idx1 < idx2)):
					if isTypeAgree(entityList[i], entity2, NELists[entityList[i].pos], NELists[entity2.pos]):
						Found = True
			else:
				if(idx2 < idx3):
					if isTypeAgree(entityList[i], entity2, NELists[entityList[i].pos], NELists[entity2.pos]):
						Found = True
		i += 1
	
	if(Found):
		return 1
	else:
		return 0

# Fungsi untuk mengekstrak fitur dari sebuah pernyataan
# statement : pernyataan
# text : teks dimana pernyataan berada
# return : list fitur
def extractFeature(statement, sentenceList):
	idxStatement = []
	maxIdx = -1
	
	# sentenceList = []
	taggedList = []
	NEList = []
	
	# sentenceList = splitSentence(text)
	
	NPList = []
	OPList = []
	i = 0
	
	for sentence in sentenceList:
		if((statement.find(sentence) != -1) or (sentence.find(statement) != -1)):
			idxStatement.append(i)
			maxIdx = i
		
		i += 1
	
	i = 0
	while(i <= maxIdx):
		taggedSentence = tagSentence(sentenceList[i])
		NESentence = extractNE(sentenceList[i])
		
		taggedList.append(taggedSentence)
		NEList.append(NESentence)
		
		if(i in idxStatement):
			NPList = NPList + extractNP(i, taggedSentence)
		# if i == maxIdx:
			# for nps in NPList:
				# print nps.str
			# print ""
		
		OPList = OPList + extractPersonOrganization(i, NESentence)
		i += 1
	
	OPList = cleanPersonOrganization(OPList)
	
	referenceList = []
	i = 0
	for entity in OPList:
		j = 0
		for phrase in NPList:
			if((entity.str != phrase.str) and (entity.pos <= phrase.pos)):
				if((isPronoun(phrase, taggedList[phrase.pos])) or (isPossessivePronoun(phrase, taggedList[phrase.pos]))):
					referenceList.append([i, j])
				if(isStringMatchPartial(phrase, entity)):
					if(len(phrase.str) < len(entity.str)):
						referenceList.append([i, j])
				if(isAbbreviation(phrase, entity)):
					if(len(phrase.str) < len(entity.str)):
						referenceList.append([i, j])
				if(isDemonstrativeNP(phrase)):
					referenceList.append([i, j])
				# if isGenitive(phrase):
					# print phrase.str
					# phrase.str = phrase.str[:phrase.str.find("'s")-1]
					# NPList[j].str = phrase.str
					# if(isStringMatchPartial(phrase, entity)):
						# if(len(phrase.str) < len(entity.str)):
							# referenceList.append([i, j])
			j += 1
		
		i += 1
	
	ruleList = []
	file = open("!candidates_rules.txt",'w')
	i = 0
	for element in referenceList:
		entity1 = OPList[element[0]]
		entity2 = NPList[element[1]]
		file.write("Entity1= "+entity1.str+"\n")
		file.write("Entity2= "+entity2.str+"\n")
		
		attr1 = isStringMatch(entity1, entity2)
		attr2 = isStringMatchPartial(entity1, entity2)
		attr3 = isAbbreviation(entity1, entity2)
		# attr4 = isPronoun(entity1, taggedList[entity1.pos])
		attr5 = isPronoun(entity2, taggedList[entity2.pos])
		attr6 = isDefiniteNP(entity2)
		attr7 = isDemonstrativeNP(entity2)
		attr8 = isProperName(entity1, entity2, taggedList[entity1.pos], taggedList[entity2.pos])
		attr9 = countSentenceDistance(entity1, entity2)
		attr10 = extractEntityType(entity1, NEList[entity1.pos])
		attr11 = extractEntityType(entity2, NEList[entity2.pos])
		attr12 = isNumberAgree(entity1, entity2, taggedList[entity1.pos], taggedList[entity2.pos])
		# attr13 = isAnyEntityBefore(entity1, entity2, sentenceList, OPList)
		attr13 = isAnySimilarEntityBefore(entity1, entity2, sentenceList, OPList, NEList)
		
		file.write("StrMatch= "+str(attr1)+"\n")
		file.write("StrMatchPart= "+str(attr2)+"\n")
		file.write("Abbr= "+str(attr3)+"\n")
		# file.write("PRP1= "+str(attr4)+"\n")
		file.write("PRP2= "+str(attr5)+"\n")
		file.write("DefNP= "+str(attr6)+"\n")
		file.write("DemNP= "+str(attr7)+"\n")
		file.write("NNP= "+str(attr8)+"\n")
		file.write("SentDist= "+str(attr9)+"\n")
		file.write("NE1= "+str(attr10)+"\n")
		file.write("NE2= "+str(attr11)+"\n")
		file.write("NumAgree= "+str(attr12)+"\n")
		file.write("AnyEntBefore= "+str(attr13)+"\n")
		file.write("\n")
		# ruleList.append([attr1, attr2, attr3, attr4, attr5, attr6, attr7, attr8, attr9, attr10, attr11, attr12, attr13])
		ruleList.append([attr1, attr2, attr3, attr5, attr6, attr7, attr8, attr9, attr10, attr11, attr12, attr13])
		
		i += 1
	file.close()
	result = [sentenceList, idxStatement, NPList, OPList, referenceList, ruleList]
	return result

def rules(feat, ent2):
	s1 = feat[0] # StrMatch
	s2 = feat[1] # StrMatchPartial
	s3 = feat[2] # Abbr
	s4 = feat[3] # PRP2
	s5 = feat[4] # DefNP
	s6 = feat[5] # DemNP
	s7 = feat[6] # NNP
	s8 = feat[7] # SentDist
	s9 = feat[8] # NE1
	s10 = feat[9] # NE2
	
	if s1 <= 0:
		if s2 <= 0:
			if s10 <= 0:
				# if s4 <= 0: return 0 # -> tambah rule untuk Abbr (s3)
				if s4 <= 0:
					if s3 <= 0:
						return 0
					else:
						return 1
				else:
					if s9 <= 1:
						if s9 <= 0: return 0
						else:
							if ent2.str in personPronouns: return 1
							else: return 0
					else:
						if s9 >= 3: return 0
						else:
							if ent2.str in objectPronouns: return 1
							else: return 0
			# else: return 0 # -> tambah rule untuk Abbr (s3)
			else:
				if s3 <= 0:
					return 0
				else:
					return 1
		else:
			if s10 <= 1 : return 1
			else: return 0
	else:
		return 1

def applyRules(statement, sentList):	
	result = extractFeature(statement, sentList)
	
	sentenceList = result[0]
	idxStatement = result[1]
	NPList = result[2]
	OPList = result[3]
	referenceList = result[4]
	ruleList = result[5]
	replacedList = []
	
	if(referenceList != []):
		prediction = []
		r = 0
		while r < len(ruleList):
			prediction.append(rules(ruleList[r], NPList[referenceList[r][1]]))
			r += 1
		i = 0
		while(i < len(prediction)):
			if(prediction[i] == 1):
				OP = OPList[referenceList[i][0]]
				NP = NPList[referenceList[i][1]]
				
				found = False
				j = i + 1
				while j < len(referenceList) and not found:
					if referenceList[j][1] == referenceList[i][1] and prediction[j] == 1 and isEntityBefore(OPList[referenceList[j][0]], NPList[referenceList[j][1]], sentenceList):
						found = True
					else:
						j += 1
				
				# if(len(NP.str) < len(OP.str)) and isEntityBefore(OP, NP, sentenceList) and referenceList[i][1] not in replacedList:# and NP.str in allPronouns:
				if isEntityBefore(OP, NP, sentenceList) and not found:# and NP.str in allPronouns:
					sentence = sentenceList[NP.pos]
					
					pleonastic = False
					if NP.str == "It" or NP.str == "it":
						pleonastic = isPleonastic(sentence)
					
					if not pleonastic:
						if(re.match(r'[A-Z].*', NP.str)):
							sentence = sentence.replace(NP.str + " ",OP.str + " ")
							sentence = sentence.replace(NP.str + "'s",OP.str + "'s")
							sentence = sentence.replace(NP.str + ",",OP.str + ",")
							NPList[referenceList[i][1]].str = OP.str
						else:
							sentence = sentence.replace(" " + NP.str + " ", " " + OP.str + " ")
							NPList[referenceList[i][1]].str = OP.str
						
						words = sentence.split()
						new_words = []
						prev = ""
						for word in words:
							if word != prev:
								new_words.append(word)
							prev = word
						sentence = ' '.join(new_words)
						sentenceList[NP.pos] = sentence
						replacedList.append(referenceList[i][1])
					
			i += 1
	return [sentenceList, idxStatement, OPList, NPList]
